package edu.faytechcc.csc289.gui;

import edu.faytechcc.csc289.data.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.*;
import javax.imageio.*;
import javax.sql.rowset.serial.*;
import javax.swing.*;
import javax.swing.table.*;

/**
 * This class handles most of the data manipulation and displaying for the
 * InventoryView and SalesView class 
 * 
 * Apr 25, 2014
 *
 * @author William Robles
 */
public class DataDisplay
{

    public void DataDisplay()
    {
    }
    
    /**
     * confirmAction method displays a confirmation dialog with custom
     * message for action being performed
     * @param ae is the ActionEvent of button being used
     * @return boolean confirm
     */
    public boolean confirmAction(ActionEvent ae)
    {
        boolean confirm = false;
        
        int response = JOptionPane.showConfirmDialog(null, "Do you want to " +
                                ae.getActionCommand() + " item?", "Confirm",
                                JOptionPane.YES_NO_OPTION, JOptionPane.
                                                            QUESTION_MESSAGE);
        if(response == JOptionPane.YES_OPTION)
        {
            confirm = true;
        }
        
        return confirm;
    }

    /**
     * returnStores method connects to DB and returns available store numbers
     *
     * @return Arraylist of available stores
     */
    public ArrayList returnStores()
    {
        ArrayList<Integer> stores = new ArrayList<>();
        SimulacraDbConnection sDc = new SimulacraDbConnection();
        ResultSet rs = sDc.getStores();

        try
        {
            while (rs.next())
            {
                stores.add(rs.getInt("Store#"));
            }

            rs.close();
        }
        catch (SQLException ex)
        {
            System.err.println("ERROR: " + ex.getMessage());
            System.exit(24);
        }

        return stores;

    }

    /**
     * *scaleImage method checks if image is correct size If size is too big
     * will scale image to 110 width 150 height
     *
     * @param pic to be scaled
     * @return ImageIcon scaled to new size
     */
    public ImageIcon scaleImage(ImageIcon pic)
    {
        if (pic.getIconWidth() > 150 || pic.getIconHeight() > 185)
        {
            pic = new ImageIcon(pic.getImage().getScaledInstance(150, 185, 0));
        }

        return pic;
    }

    /**
     * buildTable method builds a tablemodel from the resultset
     *
     * @param rS the resultset to be assigned inventory
     * @param sDB the connection to database for inventory
     * @return DefaultTableModel
     */
    public DefaultTableModel buildTable(ResultSet rS,
                                        SimulacraDbConnection sDB)
    {
        rS = sDB.getInventory();
        Vector<String> columnNames = new Vector<>();
        Vector<Object> data = new Vector<>();

        ResultSetMetaData metaData;
        try
        {
            metaData = rS.getMetaData();

            int columnCount = metaData.getColumnCount();
            for (int column = 1; column <= columnCount; column++)
            {
                columnNames.add(metaData.getColumnName(column));
            }

            while (rS.next())
            {
                Vector<Object> vector = new Vector<>();
                for (int columnIndex = 1;
                        columnIndex <= columnCount;
                        columnIndex++)
                {
                    vector.add(rS.getObject(columnIndex));
                }
                data.add(vector);
            }
            rS.close();

        }
        catch (SQLException ex)
        {
            System.err.println("ERROR: " + ex.getMessage());
            System.exit(24);
        }

        return new MyTableModel(data, columnNames);
    }

    /**
     * getFormat method finds the format for an image
     *
     * @param imagePath to read for format
     * @return string of image format
     */
    public String getFormat(String imagePath)
    {
        String temp = imagePath.toLowerCase();
        String format = "BMP";

        if (temp.endsWith(".png"))
        {
            format = "PNG";
        }
        else if (temp.endsWith(".gif"))
        {
            format = "GIF";
        }
        else if (temp.endsWith(".jpg"))
        {
            format = "JPEG";
        }

        return format;
    }

    /**
     * Converts a given Image into a BufferedImage
     *
     * @param img The Image to be converted
     * @return The converted BufferedImage
     */
    public BufferedImage toBufferedImage(Image img)
    {
        if (img instanceof BufferedImage)
        {
            return (BufferedImage) img;
        }

        // Create a buffered image with transparency
        BufferedImage bimage = new BufferedImage(img.getWidth(null),
                img.getHeight(null),
                BufferedImage.TYPE_INT_ARGB);

        // Draw the image on to the buffered image
        Graphics2D bGr = bimage.createGraphics();
        bGr.drawImage(img, 0, 0, null);
        bGr.dispose();

        return bimage;
    }

    /**
     * refreshTable method refreshes the table after modification
     *
     * @param table the table to be refreshed
     * @param rS the updated resultset to be applied
     * @param sBc the database connection
     */
    public void refreshTable(JTable table,
                             ResultSet rS,
                             SimulacraDbConnection sBc)
    {
        if (rS == null)
        {
            rS = sBc.getInventory();
        }

        table.setModel(buildTable(rS, sBc));
        table.removeColumn(table.getColumnModel().getColumn(table.
                getColumnCount() - 1));

        try
        {
            rS.close();
        }
        catch (SQLException ex)
        {
            JOptionPane.showMessageDialog(null,
                    "ERROR: " + ex.getMessage(),
                    "Error Message",
                    JOptionPane.ERROR_MESSAGE);
        }

    }

    /**
     * dataIsValid method checks JTextFields
     *
     * @param itemName the item name textfield
     * @param desc the item description textfield
     * @param cost the the cost textfield
     * @param retail the retail textfield
     * @param qty the qty textfield
     * @param img the selected image
     * @return boolean valid
     */
    public boolean dataIsValid(String itemName, String desc, String cost,
                               String retail, String qty, ImageIcon img)
    {

        boolean valid = false;

        if (!(itemName.isEmpty() || desc.isEmpty() || cost.isEmpty()
                || retail.isEmpty() || qty.isEmpty()))
        {
            if (img.getImage() != null)
            {
                if (isStringNumeric(cost, false))
                {
                    if (isStringNumeric(retail, false))
                    {
                        if (isStringNumeric(qty, true))
                        {
                            valid = true;
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(null,
                                    "ERROR: Whole Numbers only for Qty",
                                    "Error Message",
                                    JOptionPane.ERROR_MESSAGE);
                        }
                    }
                    else
                    {
                        JOptionPane.showMessageDialog(null,
                                "ERROR: Numbers only for Retail",
                                "Error Message",
                                JOptionPane.ERROR_MESSAGE);
                    }
                }
                else
                {
                    JOptionPane.showMessageDialog(null,
                            "ERROR: Numbers only for Cost",
                            "Error Message",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
            else
            {
                JOptionPane.showMessageDialog(null,
                        "ERROR: Please select a picture",
                        "Error Message",
                        JOptionPane.ERROR_MESSAGE);
            }
        }
        else
        {
            JOptionPane.showMessageDialog(null,
                    "ERROR: Make sure all fields have input",
                    "Error Message",
                    JOptionPane.ERROR_MESSAGE);
        }

        return valid;
    }

    /**
     * imageToBlob method converts an image to a Blob file
     *
     * @param im the image to be converted
     * @param path the image location
     * @return the converted blob
     * @throws Exception because it will never throw an exception but it makes
     * me do it any way
     */
    public Blob imageToBlob(ImageIcon im,
                            String path)
            throws Exception
    {
        BufferedImage bi = this.toBufferedImage(im.getImage());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(bi, this.getFormat(path), baos);
        byte[] bytes = baos.toByteArray();
        Blob blob = new SerialBlob(bytes);

        return blob;
    }

    /**
     * isStringNumeric method validates input for positive decimal or whole
     * numbers
     *
     * @param str String to be checked
     * @param wholeOnly boolean value true to only allow whole numbers
     * @return boolean valid
     */
    public boolean isStringNumeric(String str, boolean wholeOnly)
    {
        DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.
                getInstance();
        Boolean isDecimalSeparatorFound = false;
        char decimal = currentLocaleSymbols.getDecimalSeparator();

        boolean valid = false;

        for (char c : str.substring(0).toCharArray())
        {
            if (Character.isDigit(c))
            {
                valid = true;
            }
            else if (c == decimal && !isDecimalSeparatorFound && wholeOnly == false)
            {
                isDecimalSeparatorFound = true;
            }
            else
            {
                valid = false;
                break;
            }

        }

        return valid;
    }

}

/**
 * MyTableModel class is used to set datatypes for columns
 */
class MyTableModel
        extends DefaultTableModel
{

    public MyTableModel(Vector rowData,
                        Vector columnNames)
    {
        super(rowData,
                columnNames);
    }

    @Override
    public Class getColumnClass(int col)
    {
        if (getRowCount() == 0)
        {
            return Object.class;
        }
        else
        {
            Object cellValue = getValueAt(0, col);
            return cellValue.getClass();
        }
    }
    
    @Override
    public boolean isCellEditable(int row, int column)
    {
        return false;
    }
}
